home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / JPopupMenu.java < prev    next >
Text File  |  1998-06-30  |  69KB  |  2,103 lines

  1. /*
  2.  * @(#)JPopupMenu.java    1.93 98/06/26
  3.  * 
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package com.sun.java.swing;
  22.  
  23. import java.awt.*;
  24. import java.awt.event.*;
  25. import java.io.IOException;
  26. import java.io.ObjectInputStream;
  27. import java.io.ObjectOutputStream;
  28. import java.io.Serializable;
  29. import java.beans.*;
  30.  
  31. import java.util.Locale;
  32. import java.util.Vector;
  33. import java.util.Hashtable;
  34. import com.sun.java.accessibility.*;
  35. import com.sun.java.swing.plaf.PopupMenuUI;
  36. import com.sun.java.swing.plaf.ComponentUI;
  37. import com.sun.java.swing.event.*;
  38.  
  39. import java.applet.Applet;
  40.  
  41. /**
  42.  * An implementation of a Popup Menu -- a small window which pops up
  43.  * and displays a series of choices. A JPopupMenu is used for the
  44.  * menu that appears when the user selects an item on the menu bar.
  45.  * It is also used for "pull-right" menu that appears when the
  46.  * selects a menu item that activates it. Finally, a JPopupMenu
  47.  * can also be used anywhere else you want a menu to appear -- for
  48.  * example, when the user right-clicks in a specified area.
  49.  * <p>
  50.  * For the keyboard keys used by this component in the standard Look and
  51.  * Feel (L&F) renditions, see the
  52.  * <a href="doc-files/Key-Index.html#JPopupMenu">JPopupMenu</a> key assignments.
  53.  * <p>
  54.  * Warning: serialized objects of this class will not be compatible with
  55.  * future swing releases.  The current serialization support is appropriate 
  56.  * for short term storage or RMI between Swing1.0 applications.  It will
  57.  * not be possible to load serialized Swing1.0 objects with future releases
  58.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  59.  * baseline for the serialized form of Swing objects.
  60.  *
  61.  * @version 1.93 06/26/98
  62.  * @author Georges Saab
  63.  * @author David Karlton
  64.  * @author Arnaud Weber
  65.  */
  66. public class JPopupMenu extends JComponent implements Accessible,MenuElement {
  67.     transient  Component invoker;
  68.     transient  Popup popup;
  69.     transient  Frame frame;
  70.     private    String     label                   = null;
  71.     private    boolean   paintBorder              = true;  
  72.     private    Insets    margin                   = null;
  73.     private    int desiredLocationX,desiredLocationY;
  74.     private    int lastPopupType = LIGHT_WEIGHT_POPUP;
  75.  
  76.     private static final Object heavyPopupCacheKey = 
  77.         new StringBuffer("JPopupMenu.heavyPopupCache");
  78.     private static final Object lightPopupCacheKey = 
  79.         new StringBuffer("JPopupMenu.lightPopupCache");
  80.     private static final Object mediumPopupCacheKey = 
  81.         new StringBuffer("JPopupMenu.mediumPopupCache");
  82.     private static final Object defaultLWPopupEnabledKey = 
  83.         new StringBuffer("JPopupMenu.defaultLWPopupEnabledKey");
  84.  
  85.     private static final int MAX_CACHE_SIZE = 5;
  86.     private transient  MouseGrabber mouseGrabber;
  87.     private boolean lightWeightPopupEnabled = true;
  88.  
  89.     /** A light weight popup is used when it fits and light weight popups are enabled **/
  90.     private static final int LIGHT_WEIGHT_POPUP   = 0;
  91.  
  92.     /** A "Medium weight" popup is a panel. We use this when downgrading an heavy weight in
  93.      *  dialogs
  94.      */
  95.     private static final int MEDIUM_WEIGHT_POPUP  = 1;
  96.  
  97.     /** A popup implemented with a window */
  98.     private static final int HEAVY_WEIGHT_POPUP   = 2;
  99.  
  100.     /*
  101.      * Model for the selected subcontrol
  102.      */
  103.     private SingleSelectionModel selectionModel;
  104.  
  105.     /**
  106.      *  Set the default value for the <b>lightWeightPopupEnabled</b>
  107.      *  property.
  108.      */
  109.     /* Pending(arnaud) this property should scope to awt-context */
  110.     public static void setDefaultLightWeightPopupEnabled(boolean aFlag) {
  111.         SwingUtilities.appContextPut(defaultLWPopupEnabledKey, 
  112.                                      new Boolean(aFlag));
  113.     }
  114.  
  115.     /** 
  116.      *  Return the default value for the <b>lightWeightPopupEnabled</b> 
  117.      *  property.
  118.      */
  119.     public static boolean getDefaultLightWeightPopupEnabled() {
  120.         Boolean b = (Boolean)
  121.             SwingUtilities.appContextGet(defaultLWPopupEnabledKey);
  122.         if (b == null) {
  123.             SwingUtilities.appContextPut(defaultLWPopupEnabledKey, 
  124.                                          Boolean.TRUE);
  125.             return true;
  126.         }
  127.         return b.booleanValue();
  128.     }
  129.  
  130.     private static Hashtable getHeavyPopupCache() {
  131.         Hashtable cache = 
  132.             (Hashtable)SwingUtilities.appContextGet(heavyPopupCacheKey);
  133.         if (cache == null) {
  134.             cache = new Hashtable(2);
  135.             SwingUtilities.appContextPut(heavyPopupCacheKey, cache);
  136.         }
  137.         return cache;
  138.     }
  139.  
  140.     private static Vector getLightPopupCache() {
  141.         Vector cache = 
  142.             (Vector)SwingUtilities.appContextGet(lightPopupCacheKey);
  143.         if (cache == null) {
  144.             cache = new Vector();
  145.             SwingUtilities.appContextPut(lightPopupCacheKey, cache);
  146.         }
  147.         return cache;
  148.     }
  149.  
  150.     private static Vector getMediumPopupCache() {
  151.         Vector cache = 
  152.             (Vector)SwingUtilities.appContextGet(mediumPopupCacheKey);
  153.         if (cache == null) {
  154.             cache = new Vector();
  155.             SwingUtilities.appContextPut(mediumPopupCacheKey, cache);
  156.         }
  157.         return cache;
  158.     }
  159.  
  160.     static synchronized void recycleHeavyPopup(Popup aPopup) {
  161.         Vector cache;
  162.         final Frame  f = getFrame((Component)aPopup);
  163.         Hashtable heavyPopupCache = getHeavyPopupCache();
  164.         if (heavyPopupCache.containsKey(f)) {
  165.             cache = (Vector)heavyPopupCache.get(f);
  166.         } else {
  167.             cache = new Vector();
  168.             heavyPopupCache.put(f, cache);
  169.             // Clean up if the Frame is closed
  170.             f.addWindowListener(new WindowAdapter() {
  171.                 public void windowClosed(WindowEvent e) {
  172.                     Hashtable heavyPopupCache2 = getHeavyPopupCache();
  173.                     heavyPopupCache2.remove(f);
  174.                 }
  175.             });
  176.         }
  177.         
  178.         if(cache.size() < MAX_CACHE_SIZE) 
  179.             cache.addElement(aPopup);
  180.     }
  181.  
  182.     static synchronized Popup getRecycledHeavyPopup(Frame f) {
  183.         Vector cache;
  184.         Hashtable heavyPopupCache = getHeavyPopupCache();
  185.         if (heavyPopupCache.containsKey(f)) {
  186.             cache = (Vector)heavyPopupCache.get(f);
  187.         } else {
  188.             return null;
  189.         }
  190.         int c;
  191.         if((c=cache.size()) > 0) {
  192.             Popup r = (Popup)cache.elementAt(0);
  193.             cache.removeElementAt(0);
  194.             return r;
  195.         }
  196.         return null;
  197.     }
  198.  
  199.     
  200.     static synchronized void recycleLightPopup(Popup aPopup) {
  201.         Vector lightPopupCache = getLightPopupCache();
  202.         if(lightPopupCache.size() < MAX_CACHE_SIZE) 
  203.             lightPopupCache.addElement(aPopup);
  204.     }
  205.  
  206.     static synchronized Popup getRecycledLightPopup() {
  207.         Vector lightPopupCache = getLightPopupCache();
  208.         int c;
  209.         if((c=lightPopupCache.size()) > 0) {
  210.             Popup r = (Popup)lightPopupCache.elementAt(0);
  211.             lightPopupCache.removeElementAt(0);
  212.             return r;
  213.         }
  214.         return null;
  215.     }
  216.  
  217.     
  218.     static synchronized void recycleMediumPopup(Popup aPopup) {
  219.         Vector mediumPopupCache = getMediumPopupCache();
  220.         if(mediumPopupCache.size() < MAX_CACHE_SIZE) 
  221.             mediumPopupCache.addElement(aPopup);
  222.     }
  223.  
  224.     static synchronized Popup getRecycledMediumPopup() {
  225.         Vector mediumPopupCache = getMediumPopupCache();
  226.         int c;
  227.         if((c=mediumPopupCache.size()) > 0) {
  228.             Popup r = (Popup)mediumPopupCache.elementAt(0);
  229.             mediumPopupCache.removeElementAt(0);
  230.             return r;
  231.         }
  232.         return null;
  233.     }
  234.     
  235.  
  236.     static void recyclePopup(Popup aPopup) {
  237.         if(aPopup instanceof JPanelPopup)
  238.             recycleLightPopup(aPopup);
  239.         else if(aPopup instanceof WindowPopup) 
  240.             recycleHeavyPopup(aPopup);
  241.         else if(aPopup instanceof PanelPopup) 
  242.             recycleMediumPopup(aPopup);
  243.     }
  244.     /**
  245.      * Create a JPopupMenu without an "invoker".
  246.      */
  247.     public JPopupMenu() {
  248.         this(null);
  249.     }
  250.  
  251.     /**
  252.      * Create a JPopupMenu with the specified title.
  253.      *
  254.      * @param label  The string that a UI may use to display as a title 
  255.      * for the popup menu.
  256.      */
  257.     public JPopupMenu(String label) {
  258.         this.label = label;
  259.         this.setLayout(new GridBagLayout());
  260.         this.lightWeightPopupEnabled = JPopupMenu.getDefaultLightWeightPopupEnabled();
  261.         setSelectionModel(new DefaultSingleSelectionModel());
  262.         addMouseListener(new MouseAdapter() {});
  263.         updateUI();
  264.     }
  265.  
  266.  
  267.  
  268.     /**
  269.      * Returns the L&F object that renders this component.
  270.      *
  271.      * @return the PopupMenuUI object that renders this component
  272.      */
  273.     public PopupMenuUI getUI() {
  274.         return (PopupMenuUI)ui;
  275.     }
  276.     
  277.     /**
  278.      * Sets the L&F object that renders this component.
  279.      *
  280.      * @param ui the new PopupMenuUI L&F object
  281.      * @see UIDefaults#getUI
  282.      * @beaninfo
  283.      * description: The popup menu UI delegate
  284.      *       bound: true
  285.      *      expert: true
  286.      *      hidden: true
  287.      */
  288.     public void setUI(PopupMenuUI ui) {
  289.         super.setUI(ui);
  290.     }
  291.     
  292.     /**
  293.      * Notification from the UIFactory that the L&F has changed. 
  294.      * Called to replace the UI with the latest version from the 
  295.      * UIFactory.
  296.      *
  297.      * @see JComponent#updateUI
  298.      */
  299.     public void updateUI() {
  300.         setUI((PopupMenuUI)UIManager.getUI(this));
  301.     }
  302.  
  303.  
  304.     /**
  305.      * Returns the name of the L&F class that renders this component.
  306.      *
  307.      * @return "PopupMenuUI"
  308.      * @see JComponent#getUIClassID
  309.      * @see UIDefaults#getUI
  310.      */
  311.     public String getUIClassID() {
  312.         return "PopupMenuUI";
  313.     }
  314.  
  315.  
  316.     /**
  317.      * Returns the model object that handles single selections.
  318.      *
  319.      * @return the SingleSelectionModel in use
  320.      * @see SingleSelectionModel
  321.      */
  322.     public SingleSelectionModel getSelectionModel() {
  323.         return selectionModel;
  324.     }
  325.  
  326.     /**
  327.      * Set the model object to handle single selections.
  328.      *
  329.      * @param model the SingleSelectionModel to use
  330.      * @see SingleSelectionModel
  331.      * @beaninfo
  332.      * description: The selection model for the popup menu
  333.      *      expert: true
  334.      */
  335.     public void setSelectionModel(SingleSelectionModel model) {
  336.         selectionModel = model;
  337.     }
  338.  
  339.     /**
  340.      * Appends the specified menu item to the end of this menu. 
  341.      *
  342.      * @param c the JMenuItem to add
  343.      * @return the JMenuItem added.
  344.      */
  345.     public JMenuItem add(JMenuItem menuItem) {
  346.         GridBagConstraints gbc = new GridBagConstraints();
  347.         gbc.fill = GridBagConstraints.HORIZONTAL;
  348.         gbc.gridx = 0;
  349.         gbc.gridy = getComponentCount()+1;
  350.         super.add(menuItem, gbc);
  351.         return menuItem;
  352.     }
  353.  
  354.     /**
  355.      * Appends the specified component to the end of this menu. 
  356.      *
  357.      * @param c the Component to add
  358.      * @return the Component added.
  359.      */
  360.     public Component add(Component c) {
  361.         GridBagConstraints gbc = new GridBagConstraints();
  362.         gbc.fill = GridBagConstraints.HORIZONTAL;
  363.         gbc.gridx = 0;
  364.         gbc.gridy = getComponentCount()+1;
  365.         super.add(c, gbc);
  366.         return c;
  367.     }
  368.  
  369.     /**
  370.      * Append a new menuitem to the end of the menu which 
  371.      * dispatches the specified Action object.
  372.      *
  373.      * @param a the Action to add to the menu
  374.      * @see Action
  375.      */
  376.     public JMenuItem add(Action a) {
  377.         JMenuItem mi = new JMenuItem((String)a.getValue(Action.NAME),
  378.                                      (Icon)a.getValue(Action.SMALL_ICON));
  379.         mi.setHorizontalTextPosition(JButton.RIGHT);
  380.         mi.setVerticalTextPosition(JButton.CENTER);
  381.         mi.setEnabled(a.isEnabled());
  382.         mi.addActionListener(a);
  383.         add(mi);
  384.         PropertyChangeListener actionPropertyChangeListener = 
  385.             createActionChangeListener(mi);
  386.         a.addPropertyChangeListener(actionPropertyChangeListener);
  387.         return mi;
  388.     }
  389.  
  390.     protected PropertyChangeListener createActionChangeListener(JMenuItem b) {
  391.         return new ActionChangedListener(b);
  392.     }
  393.  
  394.     private class ActionChangedListener implements PropertyChangeListener {
  395.         JMenuItem menuItem;
  396.         
  397.         ActionChangedListener(JMenuItem mi) {
  398.             super();
  399.             this.menuItem = mi;
  400.         }
  401.         public void propertyChange(PropertyChangeEvent e) {
  402.             String propertyName = e.getPropertyName();
  403.             if (e.getPropertyName().equals(Action.NAME)) {
  404.                 String text = (String) e.getNewValue();
  405.                 menuItem.setText(text);
  406.             } else if (propertyName.equals("enabled")) {
  407.                 Boolean enabledState = (Boolean) e.getNewValue();
  408.                 menuItem.setEnabled(enabledState.booleanValue());
  409.             }
  410.         }
  411.     }
  412.  
  413.     /**
  414.      * When displaying the popup, JPopupMenu choose to use a light weight popup if
  415.      * it fits. This method allows you to disable this feature. You have to do disable
  416.      * it if your application mixes light weight and heavy weights components.
  417.      * @beaninfo
  418.      * description: Determines whether lightweight popups are used when possible
  419.      *      expert: true
  420.      */
  421.     public void setLightWeightPopupEnabled(boolean aFlag) {
  422.         lightWeightPopupEnabled = aFlag;
  423.     }
  424.  
  425.     /**
  426.      * Returns true if lightweight (all-Java) popups are in use,
  427.      * or false if heavyweight (native peer) popups are being used.
  428.      *
  429.      * @return true if lightweight popups are in use
  430.      */
  431.     public boolean isLightWeightPopupEnabled() {
  432.         return lightWeightPopupEnabled;
  433.     }
  434.  
  435.     /**
  436.      * Returns the popup menu's label
  437.      * @see setLabel
  438.      */
  439.     public String getLabel() {
  440.         return label;
  441.     }
  442.     
  443.     /**
  444.      * Sets the popup menu's label.  Different Look and Feels may choose
  445.      * to display or not display this.
  446.      * @param label the label for the popup menu
  447.      * @see getText
  448.      * @beaninfo
  449.      * description: The label for the popup menu. 
  450.      *       bound: true
  451.      */
  452.     public void setLabel(String label) {
  453.         String oldValue = label;
  454.         this.label = label;
  455.         firePropertyChange("label", oldValue, label);
  456.         if (accessibleContext != null) {
  457.             accessibleContext.firePropertyChange(
  458.                 AccessibleContext.ACCESSIBLE_VISIBLE_DATA_PROPERTY,
  459.                 oldValue, label);
  460.         }
  461.         invalidate();
  462.         repaint();
  463.     }
  464.  
  465.     /*
  466.      * Appends a new separator at the end of the menu.
  467.      */
  468.     public void addSeparator() {
  469.         add(new JSeparator());
  470.     }
  471.  
  472.     /**
  473.      * Inserts a menu item for the specified Action object at a given
  474.      * position.
  475.      *
  476.      * @param component  the Action object to insert
  477.      * @param index      an int specifying the position at which
  478.      *                   to insert the Action, where 0 is the first
  479.      * @see Action
  480.      */
  481.     public void insert(Action a, int index) {
  482.         throw new Error("void insert(Action, int) {} not yet implemented");
  483.     }
  484.  
  485.     /**
  486.      * Inserts the specified component into the menu at a given
  487.      * position.
  488.      *
  489.      * @param component  the Component to insert
  490.      * @param index      an int specifying the position at which
  491.      *                   to insert the component, where 0 is the first
  492.      */
  493.     public void insert(Component component, int index) {
  494.         if (index < 0) {
  495.             throw new IllegalArgumentException("index less than zero.");
  496.         }
  497.  
  498.         int nitems = getComponentCount();
  499.         Vector tempItems = new Vector();
  500.  
  501.         /* Remove the item at index, nitems-index times 
  502.            storing them in a temporary vector in the
  503.            order they appear on the menu.
  504.            */
  505.         for (int i = index ; i < nitems; i++) {
  506.             tempItems.addElement(getComponent(index));
  507.             remove(index);
  508.         }
  509.  
  510.         add(component);
  511.  
  512.         /* Add the removed items back to the menu, they are
  513.            already in the correct order in the temp vector.
  514.            */
  515.         for (int i = 0; i < tempItems.size()  ; i++) {
  516.             add((Component)tempItems.elementAt(i));
  517.         }
  518.     }
  519.  
  520.     /**
  521.      *  Add a PopupMenu listener
  522.      *
  523.      * param l  the PopupMenuListener to add
  524.      */
  525.     public void addPopupMenuListener(PopupMenuListener l) {
  526.         listenerList.add(PopupMenuListener.class,l);
  527.     }
  528.  
  529.     /**
  530.      * Remove a PopupMenu listener
  531.      *
  532.      * param l  the PopupMenuListener to remove
  533.      */
  534.     public void removePopupMenuListener(PopupMenuListener l) {
  535.         listenerList.remove(PopupMenuListener.class,l);
  536.     }
  537.  
  538.     /**
  539.      * Notifies PopupMenuListeners that this popup menu will become
  540.      * visible
  541.      */
  542.     protected void firePopupMenuWillBecomeVisible() {
  543.         Object[] listeners = listenerList.getListenerList();
  544.         PopupMenuEvent e=null;
  545.         for (int i = listeners.length-2; i>=0; i-=2) {
  546.             if (listeners[i]==PopupMenuListener.class) {
  547.                 if (e == null)
  548.                     e = new PopupMenuEvent(this);
  549.                 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeVisible(e);
  550.             }
  551.         }    
  552.     }
  553.     
  554.     /**
  555.      * Notifies PopupMenuListeners that this popup menu will become
  556.      * invisible
  557.      */
  558.     protected void firePopupMenuWillBecomeInvisible() {
  559.         Object[] listeners = listenerList.getListenerList();
  560.         PopupMenuEvent e=null;
  561.         for (int i = listeners.length-2; i>=0; i-=2) {
  562.             if (listeners[i]==PopupMenuListener.class) {
  563.                 if (e == null)
  564.                     e = new PopupMenuEvent(this);
  565.                 ((PopupMenuListener)listeners[i+1]).popupMenuWillBecomeInvisible(e);
  566.             }
  567.         }            
  568.     }
  569.     
  570.     /**
  571.      * Notifies PopupMenuListeners that this popup menu is canceled
  572.      */
  573.     protected void firePopupMenuCanceled() {
  574.         Object[] listeners = listenerList.getListenerList();
  575.         PopupMenuEvent e=null;
  576.         for (int i = listeners.length-2; i>=0; i-=2) {
  577.             if (listeners[i]==PopupMenuListener.class) {
  578.                 if (e == null)
  579.                     e = new PopupMenuEvent(this);
  580.                 ((PopupMenuListener)listeners[i+1]).popupMenuCanceled(e);
  581.             }
  582.         }    
  583.     }
  584.  
  585.     /**
  586.      * Layout the container so that it uses the minimum space
  587.      * needed to display its contents.
  588.      */
  589.     public void pack() {
  590.         if(popup != null)
  591.             popup.pack();
  592.     }
  593.  
  594.     private Popup createLightWeightPopup() {
  595.         Popup popup;
  596.         popup = JPopupMenu.getRecycledLightPopup();
  597.         if(popup == null) {
  598.             popup = new JPanelPopup();
  599.         }
  600.         return popup;
  601.     }
  602.     
  603.     private Popup createMediumWeightPopup() {
  604.         Popup popup;
  605.         popup = JPopupMenu.getRecycledMediumPopup();
  606.         if(popup == null) {
  607.             popup = new PanelPopup();
  608.         }
  609.         return popup;
  610.     }
  611.  
  612.     private Popup createHeavyWeightPopup() {
  613.         Frame frame = getFrame(invoker);
  614.  
  615.         if (frame != null) {
  616.             popup = JPopupMenu.getRecycledHeavyPopup(frame);
  617.         } else {
  618.             frame = new Frame();
  619.         }
  620.         if (popup == null)
  621.             popup = new WindowPopup(frame);
  622.  
  623.         return popup;
  624.     }
  625.  
  626.     private boolean popupFit(Rectangle popupRectInScreen) {
  627.         if(invoker != null) {
  628.             Container parent;
  629.             for(parent = invoker.getParent(); parent != null ; parent = parent.getParent()) {
  630.                 if(parent instanceof JFrame || parent instanceof JDialog) {
  631.                     return SwingUtilities.isRectangleContainingRectangle(parent.getBounds(),popupRectInScreen);
  632.                 } else if(parent instanceof JApplet) {
  633.                     Rectangle r = parent.getBounds();
  634.                     Point p  = parent.getLocationOnScreen();
  635.  
  636.                     r.x = p.x;
  637.                     r.y = p.y;
  638.                     return SwingUtilities.isRectangleContainingRectangle(r,popupRectInScreen);
  639.                 } else if(parent instanceof java.awt.Frame) {
  640.                     return SwingUtilities.isRectangleContainingRectangle(parent.getBounds(),popupRectInScreen);                    
  641.                 }
  642.             }
  643.         }
  644.         return false;
  645.     }
  646.  
  647.     private boolean ancestorIsDialog(Component i) {
  648.         Container parent;
  649.         for(parent = i.getParent() ; parent != null ; parent = parent.getParent())
  650.             if(parent instanceof java.awt.Dialog)
  651.                 return true;
  652.         return false;
  653.     }
  654.  
  655.     private void replacePopup(int newType) {
  656.         popup.removeComponent(this);
  657.         recyclePopup(popup);
  658.         switch(newType) {
  659.         case LIGHT_WEIGHT_POPUP:
  660.             popup = createLightWeightPopup();
  661.             break;
  662.         case MEDIUM_WEIGHT_POPUP:
  663.             popup = createMediumWeightPopup();
  664.             break;
  665.         case HEAVY_WEIGHT_POPUP:
  666.             popup = createHeavyWeightPopup();
  667.             break;
  668.         }
  669.  
  670.         popup.setLocationOnScreen(desiredLocationX,desiredLocationY);
  671.         popup.addComponent(this,"Center");
  672.         invalidate();
  673.         popup.setBackground(getBackground());
  674.         popup.pack();
  675.     }
  676.  
  677.     /*
  678.      * Set the visibility of the popup menu.
  679.      * 
  680.      * @param b true to make the popup visible, or false to
  681.      *          hide it
  682.      * @beaninfo
  683.      * description: Makes the popup visible
  684.      */
  685.     public void setVisible(boolean b) {
  686.         // Is it a no-op?
  687.         if (b == isVisible())
  688.             return;
  689.  
  690.         // if closing, first close all Submenus
  691.         if (b == false) {
  692.             getSelectionModel().clearSelection();
  693.  
  694.             // End the grab if we're in a Frame and
  695.             // this is a toplevel popup
  696.             if (getRootPopupMenu() == this) {
  697.                 requestRemoveGrab(invoker);
  698.             }   
  699.         } else {
  700.             // This is a popupmenu with MenuElement children,
  701.             // set selection path before popping up!
  702.             if (isPopupMenu() && (getSubElements().length > 0)) {
  703.               MenuElement me[] = new MenuElement[2];
  704.               me[0]=(MenuElement)this;
  705.               me[1]=getSubElements()[0];
  706.               MenuSelectionManager.defaultManager().setSelectedPath(me);
  707.             }
  708.         }
  709.         
  710.         if(b) {
  711.             int popupType;
  712.             int newPopupType;
  713.             boolean shouldDowngradeHeavyWeight = ancestorIsDialog(invoker);
  714.  
  715.             firePopupMenuWillBecomeVisible();
  716.             switch(lastPopupType) {
  717.             case LIGHT_WEIGHT_POPUP:
  718.                 popup = createLightWeightPopup();
  719.                 break;
  720.             case MEDIUM_WEIGHT_POPUP:
  721.                 popup = createMediumWeightPopup();
  722.                 break;
  723.             case HEAVY_WEIGHT_POPUP:
  724.                 popup = createHeavyWeightPopup();
  725.                 break;
  726.             }
  727.             popupType = lastPopupType;
  728.  
  729.             popup.setLocationOnScreen(desiredLocationX,desiredLocationY);
  730.             popup.addComponent(this,"Center");
  731.             popup.setBackground(getBackground());
  732.             popup.pack();
  733.  
  734.             Rectangle popupRect = new Rectangle(desiredLocationX,desiredLocationY,
  735.                                                 popup.getWidth(),popup.getHeight());
  736.  
  737.             if(popupFit(popupRect)) {
  738.                 if(lightWeightPopupEnabled)
  739.                     newPopupType = LIGHT_WEIGHT_POPUP;
  740.                 else
  741.                     newPopupType = MEDIUM_WEIGHT_POPUP;
  742.             } else {
  743.                 if(shouldDowngradeHeavyWeight)
  744.                     newPopupType = MEDIUM_WEIGHT_POPUP;
  745.                 else
  746.                     newPopupType = HEAVY_WEIGHT_POPUP;
  747.             }
  748.  
  749.             if(newPopupType != popupType) {
  750.                 replacePopup(newPopupType);
  751.                 popupType = newPopupType;
  752.             }
  753.  
  754.             lastPopupType = popupType;
  755.             popup.show(invoker);
  756.             // Start the grab if we're in a Frame and
  757.             // this is a toplevel popup
  758.             if (getRootPopupMenu() == this) {
  759.                 requestAddGrab(invoker,popup);
  760.             }
  761.         } else if(popup != null) {
  762.             firePopupMenuWillBecomeInvisible();
  763.             popup.hide();
  764.             popup.removeComponent(this);
  765.             recyclePopup(popup);
  766.             popup = null;
  767.         }
  768.     }
  769.  
  770.     /**
  771.      * Returns true if the popupmenu is visible (currently
  772.      * being displayed).
  773.      */
  774.     public boolean isVisible() {
  775.         if(popup != null)
  776.             return popup.isShowing();
  777.         else
  778.             return false;
  779.     }
  780.  
  781.     /**
  782.      * Set the location of the upper left corner of the
  783.      * popup menu using x, y coordinates.
  784.      *
  785.      * @param x the x coordinate of the popup's new position
  786.      * @param y the y coordinate of the popup's new position
  787.      * @beaninfo
  788.      * description: The location of the popup menu.
  789.      */
  790.     public void setLocation(int x, int y) {
  791.         if(popup != null)
  792.             popup.setLocationOnScreen(x, y);
  793.         else {
  794.             desiredLocationX = x;
  795.             desiredLocationY = y;
  796.         }
  797.     }
  798.  
  799.     /**
  800.      * Returns true if the popupmenu is a stand-alone popup menu
  801.      * rather than the submenu of a JMenu.
  802.      *
  803.      * @return true if this menu is a stand-alone popup menu
  804.      */
  805.     private boolean isPopupMenu() {
  806.         return  ((invoker != null) && !(invoker instanceof JMenu));
  807.     }
  808.  
  809.     /**
  810.      * Returns the component which is the 'invoker' of this 
  811.      * popup menu.
  812.      *
  813.      * @return the Component in which the popup menu is displayed
  814.      */
  815.     public Component getInvoker() {
  816.         return this.invoker;
  817.     }
  818.  
  819.     /**
  820.      * Sets the invoker of this popupmenu -- the component in which
  821.      * the popupmenu menu is to be displayed.
  822.      *
  823.      * @param invoker the Component in which the popup menu is displayed
  824.      * @beaninfo
  825.      * description: The invoking component for the popup menu
  826.      *      expert: true
  827.      */
  828.     public void setInvoker(Component invoker) {
  829.         Component oldInvoker = this.invoker;
  830.         this.invoker = invoker;
  831.         if ((oldInvoker != this.invoker) && (ui != null)) {
  832.             ui.uninstallUI(this);
  833.             ui.installUI(this);
  834.         }               
  835.         invalidate();
  836.     }
  837.  
  838.  
  839.     /**
  840.      * Display the popupmenu at the position x,y in the coordinate
  841.      * space of the component invoker.
  842.      *
  843.      * @param invoker The component in whose space the popupmenu is to appear
  844.      * @param x the x coordinate in invoker's coordinate space at which 
  845.      * the popup menu is to be displayed
  846.      * @param y the y coordinate in invoker's coordinate space at which 
  847.      * the popup menu is to be displayed
  848.      */
  849.     public void show(Component invoker, int x, int y) {
  850.         setInvoker(invoker);
  851.         Frame newFrame = getFrame(invoker);
  852.         if (newFrame != frame) {
  853.             // Use the invoker's frame so that events 
  854.             // are propogated properly
  855.             if (newFrame!=null) {
  856.                 this.frame = newFrame;
  857.                 if(popup != null) {
  858.                     setVisible(false);
  859.                 }
  860.             }
  861.         }
  862.         Point invokerOrigin = invoker.getLocationOnScreen();
  863.         setLocation(invokerOrigin.x + x, 
  864.                     invokerOrigin.y + y);
  865.         setVisible(true);       
  866.     }
  867.  
  868.     /**
  869.      * Returns the popupmenu which is at the root of the menu system
  870.      * for this popupmenu.
  871.      *
  872.      * @return the topmost grandparent JPopupMenu
  873.      */
  874.     JPopupMenu getRootPopupMenu() {
  875.         JPopupMenu mp = this;
  876.         while((mp!=null) && (mp.isPopupMenu()!=true) &&
  877.               (mp.getInvoker() != null) &&
  878.               (mp.getInvoker().getParent() != null) &&
  879.               (mp.getInvoker().getParent() instanceof JPopupMenu)
  880.               ) {
  881.             mp = (JPopupMenu) mp.getInvoker().getParent();
  882.         }
  883.         return mp;
  884.     }
  885.  
  886.     /**
  887.      * Returns the index of the specified component.
  888.      * 
  889.      * @param  the Component to find
  890.      * @return the index of the component, where 0 is the first,
  891.      *         or -1 if the component is not found
  892.      */
  893.     public int getComponentIndex(Component c) {
  894.         int ncomponents = this.getComponentCount();
  895.         Component[] component = this.getComponents();
  896.         for (int i = 0 ; i < ncomponents ; i++) {
  897.             Component comp = component[i];
  898.             if (comp == c) 
  899.                 return i;
  900.         }
  901.         return -1;
  902.     }
  903.  
  904.     /**
  905.      * Returns the component at the specified index.
  906.      * 
  907.      * @param i  the index of the component, where 0 is the first 
  908.      * @return the Component at that index 
  909.      */
  910.     public Component getComponentAtIndex(int i) {
  911.         int ncomponents = this.getComponentCount();
  912.         if (i <= ncomponents) {
  913.             Component[] component = this.getComponents();
  914.             return component[i];
  915.         }
  916.         return null;
  917.     }
  918.  
  919.     /**
  920.      * Sets the size of the Popup window using a Dimension object.
  921.      *
  922.      * @param <code>d</code> The dimension specifying the new size 
  923.      * of this component.
  924.      * @beaninfo
  925.      * description: The size of the popup menu
  926.      */
  927.     public void setPopupSize(Dimension d) {
  928.         popup.setSize(d.width,d.height);
  929.     }
  930.  
  931.     /**
  932.      * Sets the size of the Popup window to the specified width and
  933.      * height.
  934.      *
  935.      * @param <code>width</code> The new width of the Popup in pixels.
  936.      * @param <code>height</code> The new height of the Popup in pixels.
  937.      * @beaninfo
  938.      * description: The size of the popup menu
  939.      */
  940.     public void setPopupSize(int width, int height) {
  941.         popup.setSize(width, height);
  942.     }
  943.     
  944.     /**
  945.      * Sets the currently selected component,  This will result
  946.      * in a change to the selection model.
  947.      *
  948.      * @param sel the Component to select
  949.      * @beaninfo
  950.      * description: The selected component on the popup menu
  951.      *      expert: true
  952.      *      hidden: true
  953.      */
  954.     public void setSelected(Component sel) {    
  955.         SingleSelectionModel model = getSelectionModel();
  956.         int index = getComponentIndex(sel);
  957.         model.setSelectedIndex(index);
  958.     }
  959.  
  960.     /**
  961.      * Checks whether the border should be painted.
  962.      *
  963.      * @return true if the border is painted
  964.      * @see setBorderPainted
  965.      */
  966.     public boolean isBorderPainted() {
  967.         return paintBorder;
  968.     }
  969.  
  970.     /**
  971.      * Sets whether the border should be painted.
  972.      *
  973.      * @param b if true, the border is painted.
  974.      * @see isBorderPainted
  975.      * @beaninfo
  976.      * description: Is the border of the popup menu painted
  977.      */
  978.     public void setBorderPainted(boolean b) {
  979.         paintBorder = b;
  980.         repaint();
  981.     }
  982.  
  983.     /**
  984.      * Paint the popup menu's border if BorderPainted property is true.
  985.      * 
  986.      * @see JComponent#paint
  987.      * @see JComponent#setBorder
  988.      */
  989.     protected void paintBorder(Graphics g) {    
  990.         if (isBorderPainted()) {
  991.             super.paintBorder(g);
  992.         }
  993.     }
  994.  
  995.     /**
  996.      * Returns the margin between the popupmenu's border and
  997.      * its containees.
  998.      *
  999.      * return an Insets object containing the margin values.
  1000.      */
  1001.     public Insets getMargin() {
  1002.         if(margin == null) {
  1003.             return new Insets(0,0,0,0);
  1004.         } else {
  1005.             return margin;
  1006.         }
  1007.     }
  1008.  
  1009.  
  1010.     boolean isSubPopupMenu(JPopupMenu popup) {
  1011.         int ncomponents = this.getComponentCount();
  1012.         Component[] component = this.getComponents();
  1013.         for (int i = 0 ; i < ncomponents ; i++) {
  1014.             Component comp = component[i];
  1015.             if (comp instanceof JMenu) {
  1016.                 JMenu menu = (JMenu)comp;
  1017.                 JPopupMenu subPopup = menu.getPopupMenu();
  1018.                 if (subPopup == popup)
  1019.                     return true;
  1020.                 if (subPopup.isSubPopupMenu(popup))
  1021.                     return true;
  1022.             }
  1023.         }
  1024.         return false;
  1025.     }
  1026.  
  1027. ///////////////////////////////////////////////////////////////////////////////
  1028. //// Grab Code
  1029. ///////////////////////////////////////////////////////////////////////////////
  1030.     private static Window getWindow(Component c) {
  1031.         Component w = c;
  1032.  
  1033.         while(!(w instanceof Window) && (w!=null)) {
  1034.             w = w.getParent();
  1035.         }
  1036.         return (Window)w;
  1037.     }
  1038.  
  1039.     private static Frame getFrame(Component c) {
  1040.         Component w = c;
  1041.  
  1042.         while(!(w instanceof Frame) && (w!=null)) {
  1043.             w = w.getParent();
  1044.         }
  1045.         return (Frame)w;
  1046.     }
  1047.  
  1048.     private void requestAddGrab(Component invoker,Popup aPopup) {
  1049.         Window ancestor;
  1050.         if(mouseGrabber == null)
  1051.             mouseGrabber = new MouseGrabber(this);
  1052.  
  1053.         ancestor = getWindow(invoker);
  1054.         mouseGrabber.grabContainer(ancestor,aPopup.getComponent());
  1055.     }
  1056.  
  1057.     private void requestRemoveGrab(Component invoker) {
  1058.         if(mouseGrabber != null) {
  1059.             mouseGrabber.ungrabContainers();
  1060.         }
  1061.     }
  1062.  
  1063.     private static class MouseGrabber implements MouseListener,
  1064.         MouseMotionListener,WindowListener,ComponentListener {
  1065.         JPopupMenu popupMenu;
  1066.         Vector grabbed = new Vector();
  1067.  
  1068.         public MouseGrabber(JPopupMenu pm) {
  1069.             popupMenu = pm;
  1070.         }
  1071.  
  1072.         void cancelPopupMenu() {
  1073.             popupMenu.firePopupMenuCanceled();
  1074.          MenuSelectionManager.defaultManager().clearSelectedPath();
  1075.         }
  1076.  
  1077.         void grabContainer(Container c,Component excluded) {
  1078.             if(c == excluded)
  1079.                 return;
  1080.             if(c instanceof java.awt.Window) {
  1081.                 ((java.awt.Window)c).addWindowListener(this);
  1082.                 ((java.awt.Window)c).addComponentListener(this);
  1083.                 grabbed.addElement(c);
  1084.             }
  1085.             synchronized(c.getTreeLock()) {
  1086.                 int ncomponents = c.getComponentCount();
  1087.                 Component[] component = c.getComponents();
  1088.                 for (int i = 0 ; i < ncomponents ; i++) {
  1089.                     Component comp = component[i];
  1090.                     if(!comp.isVisible() || comp == excluded)
  1091.                         continue;
  1092.                     comp.addMouseListener(this);
  1093.                     comp.addMouseMotionListener(this);
  1094.                     grabbed.addElement(comp);
  1095.                     if (comp instanceof Container) {
  1096.                         Container cont = (Container) comp;
  1097.                         grabContainer(cont,excluded);
  1098.                     } 
  1099.                 }
  1100.             }
  1101.         }    
  1102.  
  1103.         void ungrabContainers() {
  1104.             int i,c;
  1105.             Component cpn;
  1106.             for(i=0,c=grabbed.size();i<c;i++) {
  1107.                 cpn = (Component)grabbed.elementAt(i);
  1108.                 if(cpn instanceof java.awt.Window) {
  1109.                     ((java.awt.Window)cpn).removeWindowListener(this);
  1110.                     ((java.awt.Window)cpn).removeComponentListener(this);
  1111.                 } else {
  1112.                     cpn.removeMouseListener(this);
  1113.                     cpn.removeMouseMotionListener(this);
  1114.                 }
  1115.             }
  1116.             grabbed = new Vector();
  1117.         }
  1118.  
  1119.         public void mousePressed(MouseEvent e) {
  1120.             Component c = (Component)e.getSource();
  1121.             MenuSelectionManager msm = MenuSelectionManager.defaultManager();
  1122.             if(msm.isComponentPartOfCurrentMenu(popupMenu) && msm.isComponentPartOfCurrentMenu(c)) {
  1123.                 return;
  1124.             } else {
  1125.                 cancelPopupMenu();
  1126.             }
  1127.         }
  1128.         
  1129.         public void mouseReleased(MouseEvent e) {
  1130.             MenuSelectionManager.defaultManager().processMouseEvent(e);
  1131.         }
  1132.         public void mouseEntered(MouseEvent e) {
  1133.             MenuSelectionManager.defaultManager().processMouseEvent(e);
  1134.         }
  1135.         public void mouseExited(MouseEvent e) {
  1136.             MenuSelectionManager.defaultManager().processMouseEvent(e);
  1137.         }
  1138.         public void mouseMoved(MouseEvent e) {
  1139.             MenuSelectionManager.defaultManager().processMouseEvent(e);
  1140.         }
  1141.         public void mouseDragged(MouseEvent e) {
  1142.             MenuSelectionManager.defaultManager().processMouseEvent(e);
  1143.         }
  1144.         public void mouseClicked(MouseEvent e) {
  1145.         }
  1146.         public void componentResized(ComponentEvent e) {
  1147.             cancelPopupMenu();
  1148.         }
  1149.         public void componentMoved(ComponentEvent e) {
  1150.             cancelPopupMenu();
  1151.         }
  1152.         public void componentShown(ComponentEvent e) {
  1153.             cancelPopupMenu();
  1154.         }
  1155.         public void componentHidden(ComponentEvent e) {
  1156.             cancelPopupMenu();
  1157.         }
  1158.         public void windowOpened(WindowEvent e) {}
  1159.         public void windowClosing(WindowEvent e) {
  1160.             cancelPopupMenu();
  1161.         }
  1162.         public void windowClosed(WindowEvent e) {
  1163.             cancelPopupMenu();
  1164.         }
  1165.         public void windowIconified(WindowEvent e) {
  1166.             cancelPopupMenu();
  1167.         }
  1168.         public void windowDeiconified(WindowEvent e) {}
  1169.         public void windowActivated(WindowEvent e) {
  1170.             /*   cancelPopupMenu(); cannot do this because
  1171.                  this might happen when using cascading heavy weight 
  1172.                  menus
  1173.                  */
  1174.         }
  1175.         public void windowDeactivated(WindowEvent e) {
  1176.             /*   cancelPopupMenu(); cannot do this because
  1177.                  this might happen when using cascading heavy weight 
  1178.                  menus
  1179.                  */
  1180.         }
  1181.     }
  1182.     
  1183.     /*
  1184.      * The following interface describes what a popup should implement.
  1185.      * We do this because JPopupMenu uses popup that can be windows or
  1186.      * panels. 
  1187.      */
  1188.     private interface Popup {
  1189.         public void setSize(int width,int height);
  1190.         public int  getWidth();
  1191.         public int  getHeight();
  1192.         public void addComponent(Component aComponent,Object constraints);
  1193.         public void removeComponent(Component c);
  1194.         public void pack();
  1195.         public void setBackground(Color c);
  1196.         public void show(Component invoker);
  1197.         public void hide();
  1198.         public boolean isShowing();
  1199.         public Rectangle getBoundsOnScreen();
  1200.         public void setLocationOnScreen(int x,int y);
  1201.         public Component getComponent();
  1202.     }
  1203.  
  1204.   /**
  1205.    * A class used to popup a window.
  1206.    * <p>
  1207.    * Warning: serialized objects of this class will not be compatible with
  1208.    * future swing releases.  The current serialization support is appropriate
  1209.    * for short term storage or RMI between Swing1.0 applications.  It will
  1210.    * not be possible to load serialized Swing1.0 objects with future releases
  1211.    * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1212.    * baseline for the serialized form of Swing objects.
  1213.    */
  1214.   class WindowPopup extends JWindow implements Popup,Serializable,Accessible {
  1215.     int saveX,saveY;
  1216.     boolean  firstShow = true;
  1217.  
  1218.     public WindowPopup(Frame f) {
  1219.       super(f);
  1220.     }
  1221.         
  1222.     public Component getComponent() {
  1223.       return this;
  1224.     }
  1225.  
  1226.     public int  getWidth() {
  1227.       return getBounds().width;
  1228.     }
  1229.  
  1230.     public int  getHeight() {
  1231.       return getBounds().height;
  1232.     }
  1233.  
  1234.     public void update(Graphics g) {
  1235.       paint(g);
  1236.     }
  1237.         
  1238.     public void show(Component invoker) {
  1239.       this.setLocation(saveX,saveY);
  1240.       this.setVisible(true);
  1241.  
  1242.       /** This hack is to workaround a bug on Solaris where the windows does not really show
  1243.        *  the first time
  1244.        */
  1245.       if(firstShow) {
  1246.         this.hide();
  1247.         this.setVisible(true);
  1248.         firstShow = false;
  1249.       }
  1250.     }
  1251.         
  1252.     public void hide() {
  1253.       super.hide();
  1254.       /** We need to call removeNotify() here because hide() does something only if
  1255.        *  Component.visible is true. When the app frame is miniaturized, the parent 
  1256.        *  frame of this frame is invisible, causing AWT to believe that this frame
  1257.        *  is invisible and causing hide() to do nothing
  1258.        */
  1259.       removeNotify();
  1260.     }
  1261.  
  1262.     public Rectangle getBoundsOnScreen() {
  1263.       return getBounds();
  1264.     }
  1265.  
  1266.     public void setLocationOnScreen(int x,int y) {
  1267.       this.setLocation(x,y);
  1268.       saveX = x;
  1269.       saveY = y;
  1270.     }
  1271.  
  1272.     public void addComponent(Component aComponent,Object constraints) {
  1273.       this.getContentPane().add(aComponent,constraints);
  1274.     }
  1275.  
  1276.     public void removeComponent(Component c) {
  1277.       this.getContentPane().remove(c);
  1278.     }
  1279.  
  1280.     /////////////////
  1281.     // Accessibility support
  1282.     ////////////////
  1283.  
  1284.     protected AccessibleContext accessibleContext = null;
  1285.     
  1286.     /**
  1287.      * Get the AccessibleContext associated with this JWindow
  1288.      *
  1289.      * @return the AccessibleContext of this JWindow
  1290.      */
  1291.     public AccessibleContext getAccessibleContext() {
  1292.       if (accessibleContext == null) {
  1293.         accessibleContext = new AccessibleWindowPopup();
  1294.       }
  1295.       return accessibleContext;
  1296.     }
  1297.  
  1298.     /**
  1299.      * The class used to obtain the accessible role for this object.
  1300.      * <p>
  1301.      * Warning: serialized objects of this class will not be compatible with
  1302.      * future swing releases.  The current serialization support is appropriate
  1303.      * for short term storage or RMI between Swing1.0 applications.  It will
  1304.      * not be possible to load serialized Swing1.0 objects with future releases
  1305.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1306.      * baseline for the serialized form of Swing objects.
  1307.      */
  1308.     protected class AccessibleWindowPopup extends AccessibleContext
  1309.     implements Serializable, AccessibleComponent {
  1310.     
  1311.       // AccessibleContext methods
  1312.       //
  1313.       /**
  1314.        * Get the role of this object.
  1315.        *
  1316.        * @return an instance of AccessibleRole describing the role of
  1317.        * the object
  1318.        * @see AccessibleRole
  1319.        */
  1320.       public AccessibleRole getAccessibleRole() {
  1321.         return AccessibleRole.WINDOW;
  1322.       }
  1323.     
  1324.       /**
  1325.        * Get the state of this object.
  1326.        *
  1327.        * @return an instance of AccessibleStateSet containing the 
  1328.        * current state set of the object
  1329.        * @see AccessibleState
  1330.        */
  1331.       public AccessibleStateSet getAccessibleStateSet() {
  1332.         AccessibleStateSet states = SwingUtilities.getAccessibleStateSet(WindowPopup.this);
  1333.         if (getFocusOwner() != null) {
  1334.           states.add(AccessibleState.ACTIVE);
  1335.         }
  1336.         return states;
  1337.       }
  1338.  
  1339.       /**
  1340.        * Get the Accessible parent of this object.  If the parent of this
  1341.        * object implements Accessible, this method should simply return
  1342.        * getParent().
  1343.        *
  1344.        * @return the Accessible parent of this object -- can be null if 
  1345.        * this object does not have an Accessible parent
  1346.        */
  1347.       public Accessible getAccessibleParent() {
  1348.         Container parent = getParent();
  1349.         if (parent instanceof Accessible) {
  1350.           return (Accessible) parent;
  1351.         } else {
  1352.           return null;
  1353.         }
  1354.       }
  1355.     
  1356.       /**
  1357.        * Get the index of this object in its accessible parent. 
  1358.        *
  1359.        * @return the index of this object in its parent; -1 if this 
  1360.        * object does not have an accessible parent.
  1361.        * @see #getAccessibleParent
  1362.        */
  1363.       public int getAccessibleIndexInParent() {
  1364.         return SwingUtilities.getAccessibleIndexInParent(WindowPopup.this);
  1365.       }
  1366.     
  1367.       /**
  1368.        * Returns the number of accessible children in the object.  If all
  1369.        * of the children of this object implement Accessible, than this
  1370.        * method should return the number of children of this object.
  1371.        *
  1372.        * @return the number of accessible children in the object.
  1373.        */
  1374.       public int getAccessibleChildrenCount() {
  1375.         return SwingUtilities.getAccessibleChildrenCount(WindowPopup.this);
  1376.       }
  1377.     
  1378.       /**
  1379.        * Return the nth Accessible child of the object.  
  1380.        *
  1381.        * @param i zero-based index of child
  1382.        * @return the nth Accessible child of the object
  1383.        */
  1384.       public Accessible getAccessibleChild(int i) {
  1385.         return SwingUtilities.getAccessibleChild(WindowPopup.this,i);
  1386.       }
  1387.     
  1388.       /**
  1389.        * Return the locale of this object.
  1390.        *
  1391.        * @return the locale of this object
  1392.        */
  1393.       public Locale getLocale() {
  1394.         return WindowPopup.this.getLocale();
  1395.       }
  1396.     
  1397.       /**
  1398.        * Get the AccessibleComponent associated with this object if one
  1399.        * exists.  Otherwise return null.
  1400.        */
  1401.       public AccessibleComponent getAccessibleComponent() {
  1402.         return this;
  1403.       }
  1404.     
  1405.     
  1406.       // AccessibleComponent methods
  1407.       //
  1408.             /**
  1409.              * Get the background color of this object.
  1410.              *
  1411.              * @return the background color, if supported, of the object; 
  1412.              * otherwise, null
  1413.              */
  1414.             public Color getBackground() {
  1415.                 return WindowPopup.this.getBackground();
  1416.             }
  1417.     
  1418.             /**
  1419.              * Set the background color of this object.
  1420.              *
  1421.              * @param c the new Color for the background
  1422.              */
  1423.             public void setBackground(Color c) {
  1424.                 WindowPopup.this.setBackground(c);
  1425.             }
  1426.     
  1427.             /**
  1428.              * Get the foreground color of this object.
  1429.              *
  1430.              * @return the foreground color, if supported, of the object; 
  1431.              * otherwise, null
  1432.              */
  1433.             public Color getForeground() {
  1434.                 return WindowPopup.this.getForeground();
  1435.             }
  1436.     
  1437.             /**
  1438.              * Set the foreground color of this object.
  1439.              *
  1440.              * @param c the new Color for the foreground
  1441.              */
  1442.             public void setForeground(Color c) {
  1443.                 WindowPopup.this.setForeground(c);
  1444.             }
  1445.     
  1446.             /**
  1447.              * Get the Cursor of this object.
  1448.              *
  1449.              * @return the Cursor, if supported, of the object; otherwise, null
  1450.              */
  1451.             public Cursor getCursor() {
  1452.                 return WindowPopup.this.getCursor();
  1453.             }
  1454.     
  1455.             /**
  1456.              * Set the Cursor of this object.
  1457.              *
  1458.              * @param c the new Cursor for the object
  1459.              */
  1460.             public void setCursor(Cursor cursor) {
  1461.                 WindowPopup.this.setCursor(cursor);
  1462.             }
  1463.     
  1464.             /**
  1465.              * Get the Font of this object.
  1466.              *
  1467.              * @return the Font,if supported, for the object; otherwise, null
  1468.              */
  1469.             public Font getFont() {
  1470.                 return WindowPopup.this.getFont();
  1471.             }
  1472.     
  1473.             /**
  1474.              * Set the Font of this object.
  1475.              *
  1476.              * @param f the new Font for the object
  1477.              */
  1478.             public void setFont(Font f) {
  1479.                 WindowPopup.this.setFont(f);
  1480.             }
  1481.     
  1482.             /**
  1483.              * Get the FontMetrics of this object.
  1484.              *
  1485.              * @param f the Font
  1486.              * @return the FontMetrics, if supported, the object; 
  1487.              * otherwise, null
  1488.              * @see getFont
  1489.              */
  1490.             public FontMetrics getFontMetrics(Font f) {
  1491.                 return WindowPopup.this.getFontMetrics(f);
  1492.             }
  1493.     
  1494.             /**
  1495.              * Determine if the object is enabled.
  1496.              *
  1497.              * @return true if object is enabled; otherwise, false
  1498.              */
  1499.             public boolean isEnabled() {
  1500.                 return WindowPopup.this.isEnabled();
  1501.             }
  1502.     
  1503.             /**
  1504.              * Set the enabled state of the object.
  1505.              *
  1506.              * @param b if true, enables this object; otherwise, disables it 
  1507.              */
  1508.             public void setEnabled(boolean b) {
  1509.                 WindowPopup.this.setEnabled(b);
  1510.             }
  1511.             
  1512.             /**
  1513.              * Determine if the object is visible.  Note: this means that the
  1514.              * object intends to be visible; however, it may not in fact be
  1515.              * showing on the screen because one of the objects this object
  1516.              * is contained by is not visible.  To determine if an object is
  1517.              * showing on the screen, use isShowing().
  1518.              *
  1519.              * @return true if object is visible; otherwise, false
  1520.              */
  1521.             public boolean isVisible() {
  1522.                 return WindowPopup.this.isVisible();
  1523.             }
  1524.     
  1525.             /**
  1526.              * Set the visible state of the object.
  1527.              *
  1528.              * @param b if true, shows this object; otherwise, hides it 
  1529.              */
  1530.             public void setVisible(boolean b) {
  1531.                 WindowPopup.this.setVisible(b);
  1532.             }
  1533.     
  1534.             /**
  1535.              * Determine if the object is showing.  Determined by checking
  1536.              * the visibility of the object and ancestors of the object.  
  1537.              * This will return true even if the object is obscured by another 
  1538.              * (for example, it is underneath a menu that was pulled 
  1539.              * down).
  1540.              *
  1541.              * @return true if object is showing; otherwise, false
  1542.              */
  1543.             public boolean isShowing() {
  1544.                 return WindowPopup.this.isShowing();
  1545.             }
  1546.     
  1547.             /** 
  1548.              * Checks if the specified point is within this object's bounds,
  1549.              * where the point's x and y coordinates are defined to be relative
  1550.              * to the coordinate system of the object. 
  1551.              *
  1552.              * @param p the Point relative to the coordinate system of the 
  1553.              * object
  1554.              * @return true if object contains Point; otherwise false
  1555.              */
  1556.             public boolean contains(Point p) {
  1557.                 return WindowPopup.this.contains(p);
  1558.             }
  1559.         
  1560.             /** 
  1561.              * Returns the location of the object on the screen.
  1562.              *
  1563.              * @return location of object on screen -- can be null if this
  1564.              * object is not on the screen
  1565.              */
  1566.             public Point getLocationOnScreen() {
  1567.                 return WindowPopup.this.getLocationOnScreen();
  1568.             }
  1569.     
  1570.             /** 
  1571.              * Gets the location of the object relative to the parent in the 
  1572.              * form of a point specifying the object's top-left corner in the
  1573.              * screen's coordinate space.
  1574.              *
  1575.              * @return An instance of Point representing the top-left corner 
  1576.              * of the objects's bounds in the coordinate space of the screen; 
  1577.              * null if this object or its parent are not on the screen
  1578.              */
  1579.             public Point getLocation() {
  1580.                 return WindowPopup.this.getLocation();
  1581.             }
  1582.     
  1583.             /** 
  1584.              * Sets the location of the object relative to the parent.
  1585.              */
  1586.             public void setLocation(Point p) {
  1587.                 WindowPopup.this.setLocation(p);
  1588.             }
  1589.     
  1590.             /** 
  1591.              * Gets the bounds of this object in the form of a Rectangle 
  1592.              * object.  The bounds specify this object's width, height, 
  1593.              * and location relative to its parent. 
  1594.              *
  1595.              * @return A rectangle indicating this component's bounds; null if 
  1596.              * this object is not on the screen.
  1597.              */
  1598.             public Rectangle getBounds() {
  1599.                 return WindowPopup.this.getBounds();
  1600.             }
  1601.     
  1602.             /** 
  1603.              * Sets the bounds of this object in the form of a Rectangle 
  1604.              * object.  The bounds specify this object's width, height, 
  1605.              * and location relative to its parent.
  1606.              *      
  1607.              * @param A rectangle indicating this component's bounds
  1608.              */
  1609.             public void setBounds(Rectangle r) {
  1610.                 WindowPopup.this.setBounds(r);
  1611.             }
  1612.     
  1613.             /** 
  1614.              * Returns the size of this object in the form of a Dimension 
  1615.              * object.  The height field of the Dimension object contains 
  1616.              * this objects's height, and the width field of the Dimension 
  1617.              * object contains this object's width. 
  1618.              *
  1619.              * @return A Dimension object that indicates the size of this 
  1620.              * component; null if this object is not on the screen
  1621.              */
  1622.             public Dimension getSize() {
  1623.                 return WindowPopup.this.getSize();
  1624.             }
  1625.     
  1626.             /** 
  1627.              * Resizes this object so that it has width width and height. 
  1628.              *      
  1629.              * @param d - The dimension specifying the new size of the object. 
  1630.              */
  1631.             public void setSize(Dimension d) {
  1632.                 WindowPopup.this.setSize(d);
  1633.             }
  1634.     
  1635.             /**
  1636.              * Returns the Accessible child, if one exists, contained at the 
  1637.              * local coordinate Point.
  1638.              *
  1639.              * @param p The point defining the top-left corner of the 
  1640.              * Accessible, given in the coordinate space of the object's 
  1641.              * parent. 
  1642.              * @return the Accessible, if it exists, at the specified 
  1643.              * location; else null
  1644.              */
  1645.             public Accessible getAccessibleAt(Point p) {
  1646.                 return SwingUtilities.getAccessibleAt(WindowPopup.this,p);
  1647.             }
  1648.     
  1649.             /**
  1650.              * Returns whether this object can accept focus or not.
  1651.              *
  1652.              * @return true if object can accept focus; otherwise false
  1653.              */
  1654.             public boolean isFocusTraversable() {
  1655.                 return WindowPopup.this.isFocusTraversable();
  1656.             }
  1657.     
  1658.             /**
  1659.              * Requests focus for this object.
  1660.              */
  1661.             public void requestFocus() {
  1662.                 WindowPopup.this.requestFocus();
  1663.             }
  1664.     
  1665.             /**
  1666.              * Adds the specified focus listener to receive focus events from
  1667.              * this component. 
  1668.              *
  1669.              * @param l the focus listener
  1670.              */
  1671.             public void addFocusListener(FocusListener l) {
  1672.                 WindowPopup.this.addFocusListener(l);
  1673.             }
  1674.     
  1675.             /**
  1676.              * Removes the specified focus listener so it no longer receives 
  1677.              * focus events from this component.
  1678.              *
  1679.              * @param l the focus listener
  1680.              */
  1681.             public void removeFocusListener(FocusListener l) {
  1682.                 WindowPopup.this.removeFocusListener(l);
  1683.             }
  1684.         } // inner class AccessibleWindowPopup
  1685.     }
  1686.  
  1687.     /**
  1688.      * A class used to popup a JPanel.
  1689.      * <p>
  1690.      * Warning: serialized objects of this class will not be compatible with
  1691.      * future swing releases.  The current serialization support is appropriate
  1692.      * for short term storage or RMI between Swing1.0 applications.  It will
  1693.      * not be possible to load serialized Swing1.0 objects with future releases
  1694.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1695.      * baseline for the serialized form of Swing objects.
  1696.      */
  1697.     class JPanelPopup extends JPanel implements Popup,Serializable {
  1698.         int desiredLocationX,desiredLocationY;
  1699.  
  1700.         public JPanelPopup() {
  1701.             super();
  1702.             setLayout(new BorderLayout());
  1703.             setDoubleBuffered(true);
  1704.             this.setOpaque(true);
  1705.         }
  1706.  
  1707.         public Component getComponent() {
  1708.             return this;
  1709.         }
  1710.  
  1711.         public void addComponent(Component aComponent,Object constraints) {
  1712.             this.add(aComponent,constraints);
  1713.         }
  1714.  
  1715.         public void removeComponent(Component c) {
  1716.             remove(c);
  1717.         }
  1718.  
  1719.         public void update(Graphics g) {
  1720.             paint(g);
  1721.         }
  1722.         
  1723.         public void pack() {
  1724.             setSize(getPreferredSize());
  1725.         }
  1726.  
  1727.  
  1728.         public void show(Component invoker) {
  1729.             Container parent = invoker.getParent();
  1730.             Window parentWindow = null;
  1731.  
  1732.             for(Container p = parent; p != null; p = p.getParent()) {
  1733.                 if(p instanceof JRootPane) {
  1734.                     parent = ((JRootPane)p).getLayeredPane();
  1735.                     for(p = parent.getParent(); p != null && !(p instanceof java.awt.Window) ; 
  1736.                         p = p.getParent());
  1737.                     parentWindow = (Window)p;
  1738.                     break;
  1739.                 } else if(p instanceof Window) {
  1740.                     parent = p;
  1741.                     parentWindow = (Window)p;
  1742.                     break;
  1743.                 }
  1744.             }
  1745.             Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  1746.             this.setLocation(p.x,p.y);
  1747.             if(parent instanceof JLayeredPane) {
  1748.                 ((JLayeredPane)parent).add(this,JLayeredPane.POPUP_LAYER,0);
  1749.             } else
  1750.                 parent.add(this);
  1751.         }
  1752.  
  1753.         public void hide() {
  1754.             Container parent = getParent();
  1755.             Rectangle r = this.getBounds();
  1756.             if(parent != null)
  1757.                 parent.remove(this);
  1758.             parent.repaint(r.x,r.y,r.width,r.height);
  1759.         }
  1760.  
  1761.         public Rectangle getBoundsOnScreen() {
  1762.             Container parent = getParent();
  1763.             if(parent != null) {
  1764.                 Rectangle r = getBounds();
  1765.                 Point p;
  1766.                 p = convertParentLocationToScreen(parent,r.x,r.y);
  1767.                 r.x = p.x;
  1768.                 r.y = p.y;
  1769.                 return r;
  1770.             } else 
  1771.                 throw new Error("getBoundsOnScreen called on an invisible popup");
  1772.         }
  1773.  
  1774.         Point convertParentLocationToScreen(Container parent,int x,int y) {
  1775.             Window parentWindow = null;
  1776.             Rectangle r;
  1777.             Container p;
  1778.             Point pt;
  1779.             for(p = this; p != null; p = p.getParent()) {
  1780.                 if(p instanceof Window) {
  1781.                     parentWindow = (Window)p;
  1782.                     break;
  1783.                 }
  1784.             }
  1785.             if(parentWindow != null) {
  1786.                 r = parentWindow.getBounds();
  1787.                 pt = new Point(x,y);
  1788.                 pt = SwingUtilities.convertPoint(parent,pt,null);
  1789.                 pt.x += r.x;
  1790.                 pt.y += r.y;
  1791.                 return pt;
  1792.             } else
  1793.                 throw new Error("convertParentLocationToScreen: no window ancestor found");                        }
  1794.  
  1795.         Point convertScreenLocationToParent(Container parent,int x,int y) {
  1796.             Window parentWindow = null;
  1797.             Rectangle r;
  1798.             for(Container p = parent; p != null; p = p.getParent()) {
  1799.                 if(p instanceof Window) {
  1800.                     parentWindow = (Window)p;
  1801.                     break;
  1802.                 }
  1803.             }
  1804.             if(parentWindow != null) {
  1805.                 Point p = new Point(x,y);
  1806.                 SwingUtilities.convertPointFromScreen(p,parent);
  1807.                 return p;
  1808.             } else
  1809.                 throw new Error("convertScreenLocationToParent: no window ancestor found");
  1810.         }
  1811.  
  1812.         public void setLocationOnScreen(int x,int y) {
  1813.             Container parent = getParent();
  1814.             if(parent != null) {
  1815.                 Point p = convertScreenLocationToParent(parent,x,y);
  1816.                 this.setLocation(p.x,p.y);
  1817.             } else {
  1818.                 desiredLocationX = x;
  1819.                 desiredLocationY = y;
  1820.             }
  1821.         }
  1822.     }
  1823.  
  1824.     /**
  1825.      * A class used to popup an AWT panel.
  1826.      * <p>
  1827.      * Warning: serialized objects of this class will not be compatible with
  1828.      * future swing releases.  The current serialization support is appropriate
  1829.      * for short term storage or RMI between Swing1.0 applications.  It will
  1830.      * not be possible to load serialized Swing1.0 objects with future releases
  1831.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  1832.      * baseline for the serialized form of Swing objects.
  1833.      */
  1834.     class PanelPopup extends Panel implements Popup,Serializable {
  1835.         int desiredLocationX,desiredLocationY;
  1836.         public PanelPopup() {
  1837.             super();
  1838.             setLayout(new BorderLayout());
  1839.         }
  1840.  
  1841.         public int getWidth() {
  1842.             return getBounds().width;
  1843.         }
  1844.  
  1845.         public int getHeight() {
  1846.             return getBounds().height;
  1847.         }
  1848.  
  1849.         public Component getComponent() {
  1850.             return this;
  1851.         }
  1852.  
  1853.         public void addComponent(Component aComponent,Object constraints) {
  1854.             this.add(aComponent,constraints);
  1855.         }
  1856.  
  1857.         public void removeComponent(Component c) {
  1858.             remove(c);
  1859.         }
  1860.  
  1861.         public void update(Graphics g) {
  1862.             paint(g);
  1863.         }
  1864.         
  1865.         public void pack() {
  1866.             setSize(getPreferredSize());
  1867.         }
  1868.  
  1869.  
  1870.         public void show(Component invoker) {
  1871.             Container parent = invoker.getParent();
  1872.             Window parentWindow = null;
  1873.  
  1874.             for(Container p = parent; p != null; p = p.getParent()) {
  1875.                 if(p instanceof JRootPane) {
  1876.                     parent = ((JRootPane)p).getLayeredPane();
  1877.                     for(p = parent.getParent(); p != null && !(p instanceof java.awt.Window) ; 
  1878.                         p = p.getParent());
  1879.                     parentWindow = (Window)p;
  1880.                     break;
  1881.                 } else if(p instanceof Window) {
  1882.                     parent = p;
  1883.                     parentWindow = (Window)p;
  1884.                     break;
  1885.                 }
  1886.             }
  1887.             Point p = convertScreenLocationToParent(parent,desiredLocationX,desiredLocationY);
  1888.             this.setLocation(p.x,p.y);
  1889.             if(parent instanceof JLayeredPane) {
  1890.                 ((JLayeredPane)parent).add(this,JLayeredPane.POPUP_LAYER,0);
  1891.             } else
  1892.                 parent.add(this);
  1893.         }
  1894.  
  1895.         public void hide() {
  1896.             Container parent = getParent();
  1897.             Rectangle r = this.getBounds();
  1898.             if(parent != null)
  1899.                 parent.remove(this);
  1900.             parent.repaint(r.x,r.y,r.width,r.height);
  1901.         }
  1902.  
  1903.         public Rectangle getBoundsOnScreen() {
  1904.             Container parent = getParent();
  1905.             if(parent != null) {
  1906.                 Rectangle r = getBounds();
  1907.                 Point p;
  1908.                 p = convertParentLocationToScreen(parent,r.x,r.y);
  1909.                 r.x = p.x;
  1910.                 r.y = p.y;
  1911.                 return r;
  1912.             } else 
  1913.                 throw new Error("getBoundsOnScreen called on an invisible popup");
  1914.         }
  1915.  
  1916.         Point convertParentLocationToScreen(Container parent,int x,int y) {
  1917.             Window parentWindow = null;
  1918.             Rectangle r;
  1919.             Container p;
  1920.             Point pt;
  1921.             for(p = this; p != null; p = p.getParent()) {
  1922.                 if(p instanceof Window) {
  1923.                     parentWindow = (Window)p;
  1924.                     break;
  1925.                 }
  1926.             }
  1927.             if(parentWindow != null) {
  1928.                 r = parentWindow.getBounds();
  1929.                 pt = new Point(x,y);
  1930.                 pt = SwingUtilities.convertPoint(parent,pt,null);
  1931.                 pt.x += r.x;
  1932.                 pt.y += r.y;
  1933.                 return pt;
  1934.             } else
  1935.                 throw new Error("convertParentLocationToScreen: no window ancestor found");                        }
  1936.  
  1937.         Point convertScreenLocationToParent(Container parent,int x,int y) {
  1938.             Window parentWindow = null;
  1939.             Rectangle r;
  1940.             for(Container p = parent; p != null; p = p.getParent()) {
  1941.                 if(p instanceof Window) {
  1942.                     parentWindow = (Window)p;
  1943.                     break;
  1944.                 }
  1945.             }
  1946.             if(parentWindow != null) {
  1947.                 Point p = new Point(x,y);
  1948.                 SwingUtilities.convertPointFromScreen(p,parent);
  1949.                 return p;
  1950.             } else
  1951.                 throw new Error("convertScreenLocationToParent: no window ancestor found");
  1952.         }
  1953.  
  1954.         public void setLocationOnScreen(int x,int y) {
  1955.             Container parent = getParent();
  1956.             if(parent != null) {
  1957.                 Point p = convertScreenLocationToParent(parent,x,y);
  1958.                 this.setLocation(p.x,p.y);
  1959.             } else {
  1960.                 desiredLocationX = x;
  1961.                 desiredLocationY = y;
  1962.             }
  1963.         }
  1964.     }
  1965.  
  1966.  
  1967. /////////////////
  1968. // Accessibility support
  1969. ////////////////
  1970.  
  1971.     /**
  1972.      * Get the AccessibleContext associated with this JComponent
  1973.      *
  1974.      * @return the AccessibleContext of this JComponent
  1975.      */
  1976.     public AccessibleContext getAccessibleContext() {
  1977.         if (accessibleContext == null) {
  1978.             accessibleContext = new AccessibleJPopupMenu();
  1979.         }
  1980.         return accessibleContext;
  1981.     }
  1982.  
  1983.     protected class AccessibleJPopupMenu extends AccessibleJComponent {
  1984.         /**
  1985.          * Get the role of this object.
  1986.          *
  1987.          * @return an instance of AccessibleRole describing the role of 
  1988.          * the object
  1989.          */
  1990.         public AccessibleRole getAccessibleRole() {
  1991.             return AccessibleRole.POPUP_MENU;
  1992.         }
  1993.     } // inner class AccessibleJPopupMenu
  1994.  
  1995. ////////////
  1996. // Serialization support.  
  1997. ////////////
  1998.     private void writeObject(ObjectOutputStream s) throws IOException {
  1999.         Vector      values = new Vector();
  2000.  
  2001.         s.defaultWriteObject();
  2002.         // Save the invoker, if its Serializable.
  2003.         if(invoker != null && invoker instanceof Serializable) {
  2004.             values.addElement("invoker");
  2005.             values.addElement(invoker);
  2006.         }
  2007.         // Save the popup, if its Serializable.
  2008.         if(popup != null && popup instanceof Serializable) {
  2009.             values.addElement("popup");
  2010.             values.addElement(popup);
  2011.         }
  2012.         // Save the frame, if its Serializable.
  2013.         if(frame != null && frame instanceof Serializable) {
  2014.             values.addElement("frame");
  2015.             values.addElement(frame);
  2016.         }
  2017.         s.writeObject(values);
  2018.     }
  2019.  
  2020.     private void readObject(ObjectInputStream s) 
  2021.         throws IOException, ClassNotFoundException {
  2022.         s.defaultReadObject();
  2023.  
  2024.         Vector          values = (Vector)s.readObject();
  2025.         int             indexCounter = 0;
  2026.         int             maxCounter = values.size();
  2027.  
  2028.         if(indexCounter < maxCounter && values.elementAt(indexCounter).
  2029.            equals("invoker")) {
  2030.             invoker = (Component)values.elementAt(++indexCounter);
  2031.             indexCounter++;
  2032.         }
  2033.         if(indexCounter < maxCounter && values.elementAt(indexCounter).
  2034.            equals("popup")) {
  2035.             popup = (Popup)values.elementAt(++indexCounter);
  2036.             indexCounter++;
  2037.         }
  2038.         if(indexCounter < maxCounter && values.elementAt(indexCounter).
  2039.            equals("frame")) {
  2040.             frame = (Frame)values.elementAt(++indexCounter);
  2041.             indexCounter++;
  2042.         }
  2043.     }
  2044.  
  2045.     
  2046.     public void processMouseEvent(MouseEvent event,MenuElement path[],MenuSelectionManager manager) {}
  2047.     public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
  2048.     }
  2049.  
  2050.     public void menuSelectionChanged(boolean isIncluded) {
  2051.         if(invoker instanceof JMenu) {
  2052.             JMenu m = (JMenu) invoker;
  2053.             if(isIncluded) 
  2054.                 m.setPopupMenuVisible(true);
  2055.             else
  2056.                 m.setPopupMenuVisible(false);
  2057.         }
  2058.         if (isPopupMenu() && !isIncluded)
  2059.           setVisible(false);
  2060.     }
  2061.  
  2062.     public MenuElement[] getSubElements() {
  2063.         MenuElement result[];
  2064.         Vector tmp = new Vector();
  2065.         int c = getComponentCount();
  2066.         int i;
  2067.         Component m;
  2068.  
  2069.         for(i=0 ; i < c ; i++) {
  2070.             m = getComponent(i);
  2071.             if(m instanceof MenuElement)
  2072.                 tmp.addElement(m);
  2073.         }
  2074.  
  2075.         result = new MenuElement[tmp.size()];
  2076.         for(i=0,c=tmp.size() ; i < c ; i++) 
  2077.             result[i] = (MenuElement) tmp.elementAt(i);
  2078.         return result;
  2079.     }
  2080.  
  2081.     public Component getComponent() {
  2082.         return this;
  2083.     }
  2084. }
  2085.  
  2086.  
  2087.  
  2088.  
  2089.  
  2090.  
  2091.  
  2092.  
  2093.  
  2094.  
  2095.  
  2096.  
  2097.  
  2098.  
  2099.  
  2100.  
  2101.  
  2102.  
  2103.